﻿# -*- coding:utf-8 -*-
#
# склад
#
#from django.forms import ModelForm
#from sklad.models import Category, Part, Unit, Waybill, Document, DocumentReceipt, DocumentDelivery
#from shm.models import Department
from itertools import chain
from collections import defaultdict

from django import forms
from django.forms.util import flatatt
from django.utils.encoding import StrAndUnicode, force_unicode
from django.utils.html import escape, conditional_escape
from django.utils.safestring import mark_safe


class CategoryWidget(forms.Widget):

    def __init__(self, attrs=None, choices=(), categories=None,):
        super(CategoryWidget, self).__init__(attrs)
        # choices can be any iterable, but we may need to render this widget
        # multiple times. Thus, collapse it into a list so it can be consumed
        # more than once.
        self.categories = categories   
        self.choices = list(choices)
      

    def render(self, name, value, attrs=None, choices=()):
        if not self.categories:  
            raise TypeError('"categories" keyword argument must be supplied obligatory.')      
    
        if value is None: value = ''
        final_attrs = self.build_attrs(attrs, name=name)
        output = [u'<select%s>' % flatatt(final_attrs)]
        #print self.choices
        #print choices
        options = self.render_options(choices, [value])
        if options:
            output.append(options)
        output.append('</select>')
        return mark_safe(u'\n'.join(output))

    def render_options(self, choices, selected_choices):
        
        def render_option(option_value, option_label):
            option_value = force_unicode(option_value)
            selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
            return u'<option value="%s"%s>%s</option>' % (
                escape(option_value), selected_html,
                conditional_escape(force_unicode(option_label)))
        '''
        def pairs(items):
            # внутренний "грязный" генератор, выдающий пары, где могут быть
            # бесполезные: с обоими пустыми head и tail
            def dirty(items):
                items = iter(items)
                head = None
                try:
                    while True:
                        item = items.next()
                        if isinstance(item, (list, tuple)):
                            yield head, item
                            head = None
                        else:
                            yield head, None
                            head = item
                except StopIteration:
                    yield head, None

            # фильтр над грязным генератором, удаляющий бесполезные пары
            return ((h, t) for h, t in dirty(items) if h or t)
        
        
        def render_item(item, sub_items, level):
            return ''.join([
                u'%s\n' % item,
                sub_items and '    %s\n' % ''.join(render_items(sub_items, level + 1)) or '',
            ])         

        # вывод списка элементов
        def render_items(items, level):
            return ''.join(render_item(h, t, level) for h, t in pairs(items))
        '''    
            
            
            
        
        # Normalize to strings.
        selected_choices = set([force_unicode(v) for v in selected_choices])
        output = []
        
        
        test =  createtree(self.categories,'parent')
        #for item in test:
        #    print u'%s' % item.name         

   
        #print render_items(self.categories, 0)
           
        
       
        #for option_value, option_label in chain(self.choices, choices):
        for option_value, option_label in test: #chain(self.categories):
        #for item in self.categories:
            #print item
            #option_value = item.id
            #option_label = item.name
            #print u'value - %s;  label - %s;' % (option_value, option_label)
            if isinstance(option_label, (list, tuple)):
                output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value)))
                for option in option_label:
                    output.append(render_option(*option))
                output.append(u'</optgroup>')
            else:
                output.append(render_option(option_value, option_label))
        return u'\n'.join(output)
        


        
def createtree(items, attribute):

    # перевод списка в dict: parent -> список детей
    parent_map = defaultdict(list)
    for item in items:
        parent_map[getattr(item, attribute)].append(item)
        #print u'%s' % getattr(item, attribute)
    
    #for item in parent_map:
    #    print u'%s' % item 
    
    # рекурсивный вывод детей одного parent'а
    def tree_level(parent):
        for item in parent_map[parent]:
            #print u'%s' % item
            yield item
            sub_items = list(tree_level(item))
            if sub_items:
                for item in sub_items:
                    yield item

    return list(tree_level(None))

 



       

'''
class CategoryWidget(forms.Widget):
    choices = [] # contrib.admin can't live without it

    #class Media:
    #    js = ['tagsfield/js/tags.js']
    #    css = {
    #        'all': ['tagsfield/css/tags.css']
    #    }

    def __init__(self, tag_choices, *args, **kwargs):
        super(TagsWidget, self).__init__(*args, **kwargs)
        self.tag_choices = tag_choices

    def value_from_datadict(self, data, files, name):
        return [v for v in data.getlist(name) if v]

    def render(self, name, value, attrs=None):
        if value is None:
            value = []
        tags_dict = dict(self.tag_choices)
        value_tags = [tags_dict.get(v, v) for v in value]
        tags = tags_dict.values()
        template = loader.get_template('tags/tag_widget.html')
        context = Context({
            'id': attrs['id'],
            'name': name,
            'tags': tags,
            'value_tags': value_tags,
            'media_url': settings.MEDIA_URL,
            'show_as_url': bool(getattr(settings, 'TAGS_URL', '')),
            'max_length': attrs.get('max_length'),
        })
        return mark_safe(template.render(context))
'''
 